#include <stdlib.h>
#include "random.h"
#include "trafgen.h"
#include "ranvar.h"

class VBR_Traffic : public TrafficGenerator {
 public:
	VBR_Traffic();
	virtual double next_interval(int&);
	inline double interval() { return (interval_); }
 protected:
	virtual void start();
	void init();
	double rate_;     			/* send rate during on time (bps) */
	double interval_; 			/* packet inter-arrival time during burst (sec) */
	double random_;
	int seqno_;
	int maxpkts_;				/*最大封包数目*/
	int maxsize_;				/*数据包的最大包长（byte）*/
	int minsize_;				/*数据包的最小包长*/
	int intervaltime_;			/*产生封包的时间间隔*/
};

static class VBRTrafficClass : public TclClass {
 public:
	VBRTrafficClass() : TclClass("Application/Traffic/VBR") {}
	TclObject* create(int, const char*const*) {
		return (new VBR_Traffic());
	}
} class_VBR_Traffic;

VBR_Traffic::VBR_Traffic() : seqno_(0)
{
					/*变量绑定，绑定变量以后要在ns-default.tcl中给出默认值，这些值在tcl脚本中使用的时候也可更改*/
	bind_bw("rate_", &rate_);
	bind("random_", &random_);
	bind("maxpkts_", &maxpkts_);
	bind("maxSize_", &maxsize_);		/*最大数据包长度*/
	bind("minSize_", &minsize_);		/*最短数据包长度*/
	bind("intervaltime_", &size_);
}

void VBR_Traffic::init()
{
	interval_ = (double)(intervaltime_ << 3)/(double)rate_;
	if (agent_)
		if (agent_->get_pkttype() != PT_TCP && agent_->get_pkttype() != PT_TFRC)
			agent_->set_pkttype(PT_VBR);		/*新的数据包类型：PT_VBR*/
}
void VBR_Traffic::start()
{
    init();
    running_ = 1;
    timeout();
}
double VBR_Traffic::next_interval(int& size)
{
	interval_ = (double)(intervaltime_ << 3)/(double)rate_;/*产生时间间隔，intervaltime的值可以在脚本中设置，如果不设置则取默认值，默认值在ns-default.tcl中设置；此外设置的rate_的值可以对数据速率进行粗调*/
	
	double t = interval_;//interval_是个定值
	if (random_)
		t += interval_ * Random::uniform(-0.7, 0.7); /*叠加随机分量，叠加随机分量之后每次产生数据包的间隔将会是区间[0.3*interval_, 1.7*interval_]中的一个随机值*/
	
	if(maxsize_<=minsize_) size=maxsize_;/*如果使用者赋值的时候maxsize_小于minsize_，这是错误的用法，就默认取maxsize_的值，这时候就成为CBR流*/
	
	else { 
		int i=int(Random::uniform(minsize_, maxsize_));/*否则，在最大包长和最小包长[minsize_, maxsize_]之间随机生成一个整数，作为数据包的长度*/	
		size=i;
	}
	if (++seqno_ < maxpkts_)
		return(t);
	else
		return(-1); 
}

